package com.winning.pmph.handleData;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.winning.pmph.entity.*;
import com.winning.pmph.service.*;
import com.winning.pmph.utils.FieldCompareUtil;
import com.winning.pmph.utils.HistoryUtils;
import com.winning.pmph.utils.KnowledgeEditUtil;
import com.winning.pmph.utils.StringUtil;
import com.winning.pmph.vo.ExcelDb;
import lombok.SneakyThrows;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import sun.misc.BASE64Decoder;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 因数据频繁清洗,导入,逻辑有很多相似的地方,提高代码复用
 */
@Component
@Transactional
public class HandleData {

    @Resource
    private Yibaomulu2022Service yibaomulu2022Service;
    @Resource
    private KnowledgeLibFieldService knowledgeLibFieldService;
    @Resource
    private TempKnowledgeService tempKnowledgeService;
    @Resource
    private TaskItemService taskItemService;
    @Resource
    private TagService tagService;
    @Resource
    private TempKnowledgeFieldService tempKnowledgeFieldService;
    @Resource
    private JournalService journalService;
    @Resource
    private RuleItemService ruleItemService;
    @Resource
    private PlatformService platformService;
    @Resource
    private ReleasedKnowledgeFieldService releasedKnowledgeFieldService;
    @Resource
    private ExerciseGroupLibService exerciseGroupLibService;
    @Resource
    private ExamOutlineDetailService examOutlineDetailService;
    @Resource
    private ExamOutlineTagService examOutlineTagService;
    @Resource
    private ExerciseEntryLibService exerciseEntryLibService;
    @Resource
    private ExamKnowledgeService examKnowledgeService;
    @Resource
    private ExamOutlineService examOutlineService;
    @Resource
    private TaskService taskService;
    @Resource
    private BookService bookService;
    @Resource
    private BookCategoryService bookCategoryService;
    @Resource
    private KnowledgeService knowledgeService;

    /**
     * 非自定义标签的导入
     */
    public void saveTag() {
        // 待导入的excel分类标签文件
        File file = new File("C:\\Users\\admin\\Desktop\\fenlei.xlsx");
        // 父级标签ID
        Tag tag = tagService.getById("0001AA10000000081881");
        parseAndSaveSubTagFile(tag, file, "0001AA10000000081884");
    }

    private void parseAndSaveSubTagFile(Tag parentTag, File file, String rootId) {
        Map<String, Tag> tagCodeMap = new HashMap<>();
        // 顶级标签的code
        tagCodeMap.put(parentTag.getTagCode(), parentTag);
        XSSFWorkbook workbook = null;
        try {
            workbook = new XSSFWorkbook(file);
            for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
                XSSFSheet sheet = workbook.getSheetAt(i);
                for (int j = 1; j <= sheet.getLastRowNum(); j++) {
                    XSSFRow row = sheet.getRow(j);
                    Tag tag = new Tag();
                    tag.setId(UUID.randomUUID().toString().replaceAll("-", ""));
                    // 分类名称
                    if (Objects.nonNull(row.getCell(0))) {
                        tag.setName(row.getCell(0).getStringCellValue());
                    }
                    // 分类编码
                    if (Objects.nonNull(row.getCell(1))) {
                        tag.setTagCode(row.getCell(1).getStringCellValue());
                    }
                    // 父级分类编码
                    String cellValue = row.getCell(1).getStringCellValue();
                    // 父类编码通过程序处理下, 如果是数字,去除最后两位是父类编码,如果是字符,去掉最后一位
                    if (isInteger(StringUtils.right(cellValue, 1))) {
                        tag.setParentCode(StringUtils.substring(cellValue, 0, cellValue.length() - 2));
                    } else {
                        tag.setParentCode(StringUtils.substring(cellValue, 0, cellValue.length() - 1));
                    }
                    tag.setSelfDefinedFlag(parentTag.isSelfDefinedFlag());
                    tag.setCreatedBy("admin");
                    tag.setUpdatedBy("admin");
                    tag.setRootId(rootId);
                    if (StringUtils.isBlank(tag.getName())) {
                        throw new RuntimeException("文件: " + file.getName() + ", 页签: " + sheet.getSheetName() + ", 第" + j + "行, 标签名称不能为空");
                    }
                    if (StringUtils.isBlank(tag.getTagCode())) {
                        throw new RuntimeException("文件: " + file.getName() + ", 页签: " + sheet.getSheetName() + ", 第" + j + "行, 标签编码不能为空");
                    }
                    if (tagCodeMap.containsKey(tag.getTagCode())) {
                        throw new RuntimeException("文件: " + file.getName() + ", 页签: " + sheet.getSheetName() + ", 第" + j + "行, 标签编码重复");
                    }
                    tagCodeMap.put(tag.getTagCode(), tag);
                    Tag cntParentTag = null;
                    if (StringUtils.isBlank(tag.getParentCode())) {
                        throw new RuntimeException("文件: " + file.getName() + ", 页签: " + sheet.getSheetName() + ", 第" + j + "行, 父标签编码不能为空");
                    } else if (!tagCodeMap.containsKey(tag.getParentCode())) {
                        throw new RuntimeException("文件: " + file.getName() + ", 页签: " + sheet.getSheetName() + ", 第" + j + "行, 父标签编码不存在");
                    } else {
                        cntParentTag = tagCodeMap.get(tag.getParentCode());
                    }
                    tag.setParentId(cntParentTag.getId());
                    tag.setLevel(cntParentTag.getLevel() + 1);
                    tag.setIndex(cntParentTag.getChildren().size());
                    cntParentTag.getChildren().add(tag);
                    tagService.saveTag(tag);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 判断是否是数字
     *
     * @param str
     * @return
     */
    private boolean isInteger(String str) {
        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
        return pattern.matcher(str).matches();
    }

    public void handleYibaomulu2022() {
        // 西药分类
        Map<String, Tag> tagMap = tagService.getBaseMapper().executeMultiSelect("WITH RECURSIVE _children AS ( " +
                "SELECT t.* FROM tag t WHERE t.PARENT_ID = '0001AA10000000081882' " +
                "UNION ALL SELECT t.* FROM tag t " +
                "INNER JOIN _children " +
                "ON t.parent_id = _children.id " +
                ") " +
                "SELECT * FROM _children").stream().collect(Collectors.toMap(Tag::getTagCode, Function.identity()));
        List<KnowledgeLibField> knowledgeLibFieldList = knowledgeLibFieldService.lambdaQuery().eq(KnowledgeLibField::getKnowledgeLibId, "0001AA100000000HSE0H")
                .orderByAsc(KnowledgeLibField::getIndex).list();
        Map<String, KnowledgeLibField> fieldMap = knowledgeLibFieldList.stream().collect(Collectors.toMap(KnowledgeLibField::getName, Function.identity()));
        Map<String, String> map = Maps.newHashMap();

        List<TempKnowledgeField> tempKnowledgeFieldList = Lists.newArrayList();
        List<TaskItem> taskItemList = Lists.newArrayList();
        List<TempKnowledge> tempKnowledgeList = Lists.newArrayList();
        List<Yibaomulu2022> list = yibaomulu2022Service.lambdaQuery().list();
        list.forEach(t -> {
            int wordsCount = 0;
            TempKnowledge tempKnowledge = new TempKnowledge();
            tempKnowledge.setName(t.getMingcheng());
            tempKnowledge.setKnowledgeLibId("0001AA100000000HSE0H");
            tempKnowledge.setIdentify("ybypml");
            tempKnowledge.setId(IdWorker.getIdStr());
            tempKnowledge.setCreatedBy("hexj");
            tempKnowledge.setUpdatedBy("hexj");
            tempKnowledgeList.add(tempKnowledge);

            map.put("药物名称", t.getMingcheng().trim());
            map.put("编号", t.getBianhao().trim());
            map.put("医保药物分类", t.getBianma().trim());
            map.put("是否标星", "");
            map.put("医保分类", t.getYibaofenlei().trim());
            map.put("剂型", StringUtils.defaultIfBlank(t.getJixing(), "").trim());
            map.put("医保支付标准", StringUtils.defaultIfBlank(t.getZhifubiaozhun(), "").trim());
            map.put("备注", StringUtils.defaultIfBlank(t.getBeizhu(), "").trim());
            map.put("协议有效期", StringUtils.defaultIfBlank(t.getXieyiyouxiaoqi(), "").trim());

            // 知识字段
            for (String t1 : fieldMap.keySet()) {
                TempKnowledgeField tempKnowledgeField = new TempKnowledgeField();
                tempKnowledgeField.setName(t1);
                tempKnowledgeField.setKind(fieldMap.get(t1).getKind());
                if (tempKnowledgeField.getKind() == 0) {
                    tempKnowledgeField.setProperty(StringEscapeUtils.unescapeHtml(map.get(t1)));
                } else if (tempKnowledgeField.getKind() == 1) {
                    // 如果最外层没有被p标签包裹,则包裹一层P标签
                    System.out.println("字段名:" + t1);
                    if (StringUtils.isNotBlank(map.get(t1))) {
                        if (!map.get(t1).startsWith("<p")) {
                            tempKnowledgeField.setProperty(StringEscapeUtils.unescapeHtml("<p>" + map.get(t1) + "</p>"));
                        } else {
                            tempKnowledgeField.setProperty(StringEscapeUtils.unescapeHtml(map.get(t1)));
                        }
                    }
                } else if (tempKnowledgeField.getKind() == 2) {
                    tempKnowledgeField.setKindValue("0001AA10000000081884");
                    tempKnowledgeField.setProperty(newTag(tagMap.get(map.get(t1)).getId()));
                } else if (tempKnowledgeField.getKind() == 3) {
                    // 单选
                    if ("是否标星".equals(t1)) {
                        tempKnowledgeField.setKindValue("16");
                        tempKnowledgeField.setProperty(t.getBianhao().contains("★") ? "137" : "138");
                    } else if ("医保分类".equals(t1)) {
                        tempKnowledgeField.setKindValue("15");
                        tempKnowledgeField.setProperty(map.get(t1).contains("甲") ? "135" : "136");
                    }
                }
                tempKnowledgeField.setKnowledgeId(tempKnowledge.getId());
                tempKnowledgeField.setKnowledgeLibFieldId(fieldMap.get(t1).getId());
                tempKnowledgeField.setIndex(fieldMap.get(t1).getIndex());
                tempKnowledgeField.setRequired(fieldMap.get(t1).getRequired());
                tempKnowledgeField.setCreatedBy("hexj");
                tempKnowledgeField.setUpdatedBy("hexj");
                wordsCount += KnowledgeEditUtil.countWords(tempKnowledgeField);
                tempKnowledgeFieldList.add(tempKnowledgeField);
            }

            // 存储子任务表
            TaskItem taskItem = new TaskItem();
            taskItem.setTaskId("1498102580667842561");
            taskItem.setKnowledgeId(tempKnowledge.getId());
            taskItem.setName(t.getMingcheng());
            taskItem.setType(0);
            taskItem.setEditor("hexj");
            taskItem.setStatus(1);
            taskItem.setFirstAuditor("hexj");
            taskItem.setWordsCount(wordsCount);
            taskItem.setCreatedBy("hexj");
            taskItem.setUpdatedBy("hexj");
            taskItemList.add(taskItem);
        });
        taskItemService.saveBatch(taskItemList);
        tempKnowledgeService.saveBatch(tempKnowledgeList);
        tempKnowledgeFieldService.saveBatch(tempKnowledgeFieldList);
    }

    /**
     * 根据tagcode获取父级标签
     *
     * @param childId
     * @return
     */
    private String newTag(String childId) {
        String id = tagService.getBaseMapper().getParentIdByChildId(childId);
        JSONArray resultArray = new JSONArray();
        JSONArray array = new JSONArray();
        if (StringUtils.isNotBlank(id)) {
            for (String s : id.split(",")) {
                array.add(s);
            }
        }
        resultArray.add(array);
        return JSON.toJSONString(resultArray);
    }

    /**
     * 处理期刊主办单位
     */
    public void handleJournalSponsor() {
        List<Journal> journalList = journalService.lambdaQuery().eq(Journal::getId, "1496315365510246401").list();
        journalList.forEach(journalItem -> {
            // 唯一标识
            String uniqueMark = journalItem.getIssn() + "***" + journalItem.getVolume() + "***" + journalItem.getIssue();
            JSONObject metadataObj = JSON.parseObject(journalItem.getMetadata());
            JSONObject publisher = metadataObj.getJSONObject("publisher");
            JSONArray jsonArray = publisher.getJSONArray("publisher-name");
            // 中文主办单位
            JSONObject sponsorObject = new JSONObject();
            sponsorObject.put("specific-use", "sponsor");
            sponsorObject.put("content", "中文主办单位");
            jsonArray.add(sponsorObject);
            // 英文主办单位
            JSONObject sponsorEnObject = new JSONObject();
            sponsorEnObject.put("xml:lang", "en");
            sponsorEnObject.put("specific-use", "sponsor");
            sponsorEnObject.put("content", "英文主办单位");
            jsonArray.add(sponsorEnObject);
            publisher.put("publisher-name", jsonArray);
            // 地址
            JSONArray jsonArrayLoc = publisher.getJSONArray("publisher-loc");
            // 中文主办单位
            JSONObject sponsorLocObject = new JSONObject();
            sponsorLocObject.put("specific-use", "sponsor");
            sponsorLocObject.put("content", "中文主办单位地址");
            jsonArrayLoc.add(sponsorLocObject);
            // 英文主办单位
            JSONObject sponsorLocEnObject = new JSONObject();
            sponsorLocEnObject.put("xml:lang", "en");
            sponsorLocEnObject.put("specific-use", "sponsor");
            sponsorLocEnObject.put("content", "英文主办单位地址");
            jsonArrayLoc.add(sponsorLocEnObject);
            publisher.put("publisher-loc", jsonArrayLoc);
            journalItem.setMetadata(metadataObj.toJSONString());
        });
    }

    private static CellStyle setStyleHead(Workbook workbook) {
        CellStyle cellStyle = workbook.createCellStyle();
        Font font = workbook.createFont();
        font.setFontHeightInPoints((short) 10);
        cellStyle.setFont(font);
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        return cellStyle;
    }

    /**
     * 导出未发布知识
     */
    public void importKnowledgeExcel() {
        // 单选或者多选
        Map<String, Map<String, String>> map = Maps.newConcurrentMap();
        List<RuleItem> ruleItemList = ruleItemService.list();
        Map<String, List<RuleItem>> ruleMap = ruleItemList.stream().collect(Collectors.groupingBy(RuleItem::getRuleId));
        Map<String, String> itemMap = null;
        for (Map.Entry<String, List<RuleItem>> m : ruleMap.entrySet()) {
            itemMap = Maps.newConcurrentMap();
            for (RuleItem ruleItem : m.getValue()) {
                itemMap.put(ruleItem.getId(), ruleItem.getName());
            }
            map.put(m.getKey(), itemMap);
        }

        List<String> knowledgeIdList = taskItemService.lambdaQuery()
                .eq(TaskItem::getTaskId, "0001AA100000000WG5I8")
                .in(TaskItem::getStatus, 1, 2)
                .in(TaskItem::getKnowledgeId, "1503568975866101761", "1503570018192588801")
                .list().stream().map(TaskItem::getKnowledgeId).collect(Collectors.toList());
        List<TempKnowledgeField> list = tempKnowledgeFieldService.lambdaQuery()
                .in(TempKnowledgeField::getKnowledgeId, knowledgeIdList)
                .isNotNull(TempKnowledgeField::getKnowledgeLibFieldId)
                .ne(TempKnowledgeField::getKnowledgeLibFieldId, "")
                .orderByAsc(TempKnowledgeField::getIndex).list();
        KnowledgeAuditPack knowledgeAuditPack = new KnowledgeAuditPack();

        Set<String> tagSet = list.stream().map(TempKnowledgeField::getKindValue).filter(t -> org.apache.commons.lang3.StringUtils.isNotBlank(t)).collect(Collectors.toSet());
        if (tagSet.size() > 0) {
            Map<String, String> tagMap = Maps.newConcurrentMap();
            List<Tag> allTag = tagService.queryTagByRootIdSet(tagSet);
            for (Tag tag : allTag) {
                tagMap.put(tag.getId(), tag.getName());
            }
            knowledgeAuditPack.setTagMap(tagMap);
        }
        // 应用平台
        Map<String, String> platformMap = Maps.newConcurrentMap();
        List<Platform> platformList = platformService.list();
        for (Platform platform : platformList) {
            platformMap.put(platform.getId(), platform.getName());
        }
        knowledgeAuditPack.setPlatformMap(platformMap);
        createExcel(list, knowledgeAuditPack, map);
    }

    private void createExcel(List<TempKnowledgeField> list, KnowledgeAuditPack knowledgeAuditPack, Map<String, Map<String, String>> dropDownMap) {
        ExcelDb excelDb = new ExcelDb();
        excelDb.setSheetName("tengxun");
        excelDb.setTitle("tengxun");
        List<String> headers = list.stream().map(TempKnowledgeField::getName).collect(Collectors.toList()).stream().distinct().collect(Collectors.toList());
        headers.add("id");
        excelDb.setHeaders(headers.stream().toArray(String[]::new));
        Map<String, List<TempKnowledgeField>> map = list.stream().collect(Collectors.groupingBy(TempKnowledgeField::getKnowledgeId));
        List<ExcelDb> excelDblist = Lists.newArrayList();
        List<String[]> data = Lists.newArrayList();
        for (List<TempKnowledgeField> fieldList : map.values()) {
            // 中成药  .startsWith("[[\"0001AA100000000814B8\""))
            /*Optional<TempKnowledgeField> first = fieldList.stream().filter(item -> item.getKind() == 2 && item.getProperty()
                    .equals("[]")).findFirst();
            if (!first.isPresent()) {
                continue;
            }*/
            String[] fieldStr = new String[headers.size()];
            for (int i = 0; i < fieldStr.length - 1; i++) {
                fieldStr[i] = getFieldValue(fieldList.get(i), knowledgeAuditPack, dropDownMap);
            }
            fieldStr[fieldStr.length - 1] = fieldList.get(0).getKnowledgeId();
            data.add(fieldStr);
        }
        excelDb.setData(data);
        excelDblist.add(excelDb);
        excelDownload(excelDblist);
    }

    @SneakyThrows
    private void excelDownload(List<ExcelDb> list) {
        Workbook workbook = new XSSFWorkbook();
        for (int m = 1; m <= list.size(); m++) {
            ExcelDb exceldb = list.get(m - 1);
            String sheetName = exceldb.getSheetName() == null ? "Sheet" + m : exceldb.getSheetName();
            String[] headers = exceldb.getHeaders();
            List<String[]> data = exceldb.getData();
            Sheet sheet = workbook.createSheet(sheetName);
            Row row1 = sheet.createRow(0);
            for (int i = 0; i < headers.length; i++) {
                Cell cell1 = row1.createCell(i);
                cell1.setCellValue(headers[i]);
                cell1.setCellStyle(setStyleHead(workbook));
            }
            for (int i = 0; i < data.size(); i++) {
                Row row2 = sheet.createRow(i + 1);
                String[] strings = data.get(i);
                for (int j = 0; j < strings.length; j++) {
                    Cell cell2 = row2.createCell(j);
                    cell2.setCellValue(strings[j]);
                }
            }
        }
        FileOutputStream fs = new FileOutputStream("C:\\Users\\admin\\Desktop\\tengxun.xlsx");
        workbook.write(fs);
        fs.close();
    }

    private String getFieldValue(KnowledgeField tempKnowledgeField, KnowledgeAuditPack knowledgeAuditPack, Map<String, Map<String, String>> map) {
        String value = "";
        value = tempKnowledgeField.getProperty();
        int kind = tempKnowledgeField.getKind();
        if (1 == kind) {
            // 富文本
            value = tempKnowledgeField.getProperty();
        } else if (2 == kind) {
            // 参照
            String tagIds = tempKnowledgeField.getProperty();
            if (org.apache.commons.lang3.StringUtils.isNotBlank(tagIds) && !org.apache.commons.lang3.StringUtils.equals(tagIds, "[]")) {
                Map<String, String> tagMap = knowledgeAuditPack.getTagMap();
                tagIds = tagIds.replaceAll("\\[\\[", "").replaceAll("]]", "").replaceAll("\"", "").replaceAll("'", "");
                String[] splitTagIds = tagIds.replaceAll("],\\[", ";").split(";");
                List<String> resultList = Lists.newArrayList();
                for (String splitTagId : splitTagIds) {
                    String[] temp = splitTagId.split(",");
                    List<String> tagNameList = Lists.newArrayList();
                    for (String s : temp) {
                        tagNameList.add(tagMap.get(s));
                    }
                    resultList.add(org.apache.commons.lang3.StringUtils.join(tagNameList, "->"));
                }
                value = org.apache.commons.lang3.StringUtils.join(resultList, ";");
            } else {
                value = "";
            }
        } else if (3 == kind || 5 == kind) {
            if (org.apache.commons.lang3.StringUtils.isNotBlank(tempKnowledgeField.getProperty()) && !org.apache.commons.lang3.StringUtils.equals(tempKnowledgeField.getProperty(), "[]")) {
                // 单选或者多选下拉
                String kindValue = tempKnowledgeField.getKindValue();
                String ruleId = tempKnowledgeField.getProperty().replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "").replaceAll("'", "");
                String[] tempStr = ruleId.split(",");
                List<String> list = Lists.newArrayList();
                for (String s : tempStr) {
                    list.add(map.get(kindValue).get(s));
                }
                value = org.apache.commons.lang3.StringUtils.join(list, ";");
            } else {
                value = "";
            }
        } else if (7 == kind) {
            // 多值输入框
            if (org.apache.commons.lang3.StringUtils.isBlank(tempKnowledgeField.getProperty()) || org.apache.commons.lang3.StringUtils.equals(tempKnowledgeField.getProperty(), "[]")) {
                value = "";
            } else {
                value = tempKnowledgeField.getProperty().replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "").replaceAll("'", "").replaceAll(",", ";");
            }
        } else if (8 == kind || 9 == kind) {
            // 关联本知识库/其他知识库
            if (org.apache.commons.lang3.StringUtils.isBlank(tempKnowledgeField.getProperty()) || org.apache.commons.lang3.StringUtils.equals(tempKnowledgeField.getProperty(), "[]")) {
                value = "";
            } else {
                JSONArray jsonArray = JSONObject.parseArray(tempKnowledgeField.getProperty());
                List<String> list = Lists.newArrayList();
                for (Object o : jsonArray) {
                    JSONObject s = (JSONObject) o;
                    list.add(s.getString("name"));
                }
                value = org.apache.commons.lang3.StringUtils.join(list, ";");
            }
        } else if (10 == kind) {
            // 关联平台
            if (org.apache.commons.lang3.StringUtils.isBlank(tempKnowledgeField.getProperty()) || org.apache.commons.lang3.StringUtils.equals(tempKnowledgeField.getProperty(), "[]")) {
                value = "";
            } else {
                Map<String, String> platformMap = knowledgeAuditPack.getPlatformMap();
                String[] platForm = tempKnowledgeField.getProperty().replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "").replaceAll("'", "").split(",");
                List<String> platNameList = Lists.newArrayList();
                for (String s : platForm) {
                    platNameList.add(platformMap.get(s));
                }
                value = org.apache.commons.lang3.StringUtils.join(platNameList, ";");
            }
        } else if (4 == kind || 11 == kind) {
            JSONObject jsonObject = JSONObject.parseObject(value);
            String paths = jsonObject.getString("paths");
            if (org.apache.commons.lang3.StringUtils.equals(paths, "[]")) {
                return "";
            }
        } else if (12 == kind) {
            // 文件
            if (org.apache.commons.lang3.StringUtils.equals(value, "[]")) {
                return "";
            }
        }
        return value;
    }

    /**
     * 批量驳回
     */
    public void batchReject() {
        // 当前用户参与审核的子任务, 都展示;
        String sql = "select ti.*, t.knowledge_lib_id, t.audit_level, t.system_type, t.enable_create" +
                " from task_item ti " +
                "left join task t on ti.task_id = t.id " +
                "where ti.deleted = " + TaskItem.NO_DELETED +
                " and ti.status != 0 and ti.status != 3 " +
                " and (ti.first_auditor = 'hexj' " +
                " || ti.second_auditor = 'hexj' " +
                " || ti.third_auditor = 'hexj') ";
        // 当前用户审核中的任务;
        sql += " and ti.task_id = '0001AA100000000WG5I8'";
        sql += " and ti.name like '%（%'";
        sql += " order by ti.updated_time desc";
        List<TaskItem> taskItemLists = taskItemService.getBaseMapper().executeMultiSelect("select * from task_item where id in ('0001AA100000000WIK0J',\n" +
                "'0001AA100000000WIK3S',\n" +
                "'1491324737032130561')");
        // 驳回
        // 记录操作历史;
        Map<String, TempKnowledge> knowledgeMap = tempKnowledgeService.lambdaQuery().in(TempKnowledge::getId,
                taskItemLists.stream().map(TaskItem::getKnowledgeId).collect(Collectors.toList())).list()
                .stream().collect(Collectors.toMap(TempKnowledge::getId, Function.identity()));
        for (TaskItem taskItem : taskItemLists) {
            TempKnowledge knowledge = knowledgeMap.get(taskItem.getKnowledgeId());
            HistoryUtils.save(knowledge.getId(), knowledge.getName(), History.OPERATE_REJECT, History.OPERATE_RESULT_SUCCESS);
            // 记录字段变更;
            FieldCompareUtil.recordChangesInKnowledgeFields(History.OPERATE_REJECT, knowledge);
            // 修改任务项;
            Integer modifiedStatus = KnowledgeEditUtil.auditStatus(knowledge.getId(), taskItem.getAuditLevel(), "reject");
            taskItem.setReject("技术批量驳回，需要补充内容");
            taskItem.setStatus(modifiedStatus);
            taskItemService.updateById(taskItem);
        }
    }

    public void checkImgType() {
        // 查找所有的行内图
        List<ReleasedKnowledgeField> fieldList = releasedKnowledgeFieldService.lambdaQuery()
                .eq(ReleasedKnowledgeField::getKind, 1)
                .and(t -> t.like(ReleasedKnowledgeField::getProperty, "rw_img bz").or()
                        .like(ReleasedKnowledgeField::getProperty, "rw_img hnt")).list();
        fieldList.forEach(fieldItem -> {
            Elements imgs = Jsoup.parse(fieldItem.getProperty()).getElementsByTag("img");
            imgs.forEach(img -> {
                if (img.attr("src").contains("image/bz/")) {
                    return;
                }
                try {
                    // 根据图片宽,高判断是否是行内图
                    // 取得图片的class样式,和src的路径,还有ID,因为有些图片可能没有id属性
                    if ("rw_img hnt".equalsIgnoreCase(StringUtils.defaultIfBlank(img.attr("class"), "").trim()) ||
                            "rw_img bz".equalsIgnoreCase(StringUtils.defaultIfBlank(img.attr("class"), "").trim())) {
                        if (img.attr("src").startsWith("data:image")) {
                            String baohanhouzhui = img.attr("src").split(";base64,")[0];
                            ImageIO.read(new FileInputStream(convertBase64ToFile(img.attr("src").split(";base64,")[1],
                                    "C:\\Users\\admin\\Desktop\\行内图\\", IdWorker.getIdStr() + "####" + fieldItem.getId() + "." +
                                            StringUtils.substringAfter(baohanhouzhui, "data:image/"))));

                        } else {
                            String fileName = StringUtils.substringAfterLast(img.attr("src"), "/");
                            FileUtils.copyURLToFile(new URL("http://192.168.111.20:8080/" +
                                            StringUtils.substringAfter(img.attr("src"), "filename=")),
                                    new File("C:\\Users\\admin\\Desktop\\行内图\\" + IdWorker.getIdStr() + "##" + fieldItem.getId() + fileName));
                        /*murl = new URL("http://192.168.111.20:8080/" + StringUtils.substringAfter(img.attr("src"), "filename=")).openStream();
                        sourceImg = ImageIO.read(murl);*/
                        }
                    }
                } catch (IOException e) {
                    System.out.println("查找图片报错:" + fieldItem.getId() + ":" + img.attr("src"));
                }
            });
        });
    }

    private File convertBase64ToFile(String fileBase64String, String filePath, String fileName) {
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file = null;
        try {
            File dir = new File(filePath);
            if (!dir.exists() && dir.isDirectory()) {//判断文件目录是否存在
                dir.mkdirs();
            }

            BASE64Decoder decoder = new BASE64Decoder();
            byte[] bfile = decoder.decodeBuffer(fileBase64String);

            file = new File(filePath + File.separator + fileName);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(bfile);
            return file;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

    public void matchExericsByQuestion() {
        List<ExamOutlineDetail> detailList = examOutlineDetailService.lambdaQuery().eq(ExamOutlineDetail::getExamOutlineId, "1508996261484871682")
                .list();
        detailList.forEach(item -> {
            item.setName(KnowledgeUnitService.parseCatalogName2KnowledgeFieldName(item.getName()));
        });
        // 最末级的细目+要点
        List<ExamOutlineTag> tagList = examOutlineTagService.lambdaQuery().eq(ExamOutlineTag::getExamOutlineId, "1508996261484871682")
                .list();
        tagList.forEach(item -> {
            item.setName(KnowledgeUnitService.parseCatalogName2KnowledgeFieldName(item.getName()));
        });
        Set<String> parentIdSet = tagList.stream().map(ExamOutlineTag::getParentId).collect(Collectors.toSet());
        Map<String, ExamOutlineTag> subTagMap = tagList.stream().filter(item -> !parentIdSet.contains(item.getId()))
                .collect(Collectors.toMap(ExamOutlineTag::getId, Function.identity()));

        for (ExamOutlineDetail outlineDetail : detailList) {
            outlineDetail.setName(StringUtils.deleteWhitespace(outlineDetail.getName() + subTagMap.get(outlineDetail.getExamOutlineTagId()).getName()));
        }

        LinkedHashMap<String, ExamOutlineDetail> detailMap = detailList.stream()
                .collect(Collectors.toMap(ExamOutlineDetail::getName, field -> field, (k1, k2) -> k1, LinkedHashMap::new));

        List<ExerciseEntryLib> list = exerciseEntryLibService.lambdaQuery().list();

        // 匹配问题
        /*list.forEach(item -> {
            String question = KnowledgeUnitService.parseCatalogName2KnowledgeFieldName(item.getQuestion());
            question = removeEle(Jsoup.parse(question).body());
            // 去除冗余字
            question = question.replace("的叙述错误的是", "").replace("关于", "")
                    .replace("的叙述不正确的是", "").replace("的叙述正确的是", "")
                    .replace("下列叙述正确的是", "").replace("下列叙述错误的是", "")
                    .replace("下列叙述不正确的是", "").replace("的描述不正确的是", "")
                    .replace("的描述正确的是", "").replace("不包括", "")
                    .replace("下列属于", "").replace("错误的是", "")
                    .replace("的描述恰当的是", "").replace("下列说法正确的是", "")
                    .replace("下列不属于", "");
            item.setNoELeQuestion(question);
        });
        Map<String, List<ExerciseEntryLib>> entryLibMap = list.stream().collect(Collectors
                .groupingBy(ExerciseEntryLib::getNoELeQuestion));*/

        // 匹配选项
        Map<String, List<ExerciseEntryLib>> entryLibMap = new HashMap<>();
        list.forEach(item -> {
            for (int i = 0; i < item.getChoiceArray().size(); i++) {
                String choice = KnowledgeUnitService.parseCatalogName2KnowledgeFieldName(item.getChoiceArray().getString(i));
                String key = removeEle(Jsoup.parse(choice).body());
                List<ExerciseEntryLib> entryLibList = entryLibMap.getOrDefault(key, new ArrayList<>());
                entryLibList.add(item);
                entryLibMap.put(key, entryLibList);
            }
        });

        Set<ExerciseEntryLib> entryLibList = new HashSet<>();
        matchByRate(detailMap, entryLibMap, entryLibList, 1f);
        matchByRate(detailMap, entryLibMap, entryLibList, 0.9f);
        matchByRate(detailMap, entryLibMap, entryLibList, 0.8f);
        matchByRate(detailMap, entryLibMap, entryLibList, 0.7f);
        matchByRate(detailMap, entryLibMap, entryLibList, 0.6f);
        matchByRate(detailMap, entryLibMap, entryLibList, 0.5f);
        matchByRate(detailMap, entryLibMap, entryLibList, 0.4f);
        matchByRate(detailMap, entryLibMap, entryLibList, 0.3f);

        Map<String, ExerciseGroupLib> groupLibMap = exerciseGroupLibService.lambdaQuery().list().stream()
                .collect(Collectors.toMap(ExerciseGroupLib::getId, Function.identity()));
        Map<String, ExerciseGroupLib> updateMap = new HashMap<>();
        entryLibList.forEach(exerciseEntryItem -> {
            for (Object examDetailId : exerciseEntryItem.getExamDetailIdArray()) {
                ExerciseGroupLib exerciseGroupLib = groupLibMap.get(exerciseEntryItem.getGroupId());
                if (!exerciseGroupLib.getExamDetailIdArray().contains(examDetailId.toString())) {
                    exerciseGroupLib.getExamDetailIdArray().add(examDetailId.toString());
                    updateMap.put(exerciseEntryItem.getGroupId(), exerciseGroupLib);
                }
            }
        });
        exerciseGroupLibService.updateBatchById(updateMap.values());
    }

    public void matchExericsByAnalyses() {
        List<ExerciseEntryLib> list = exerciseEntryLibService.lambdaQuery().isNotNull(ExerciseEntryLib::getAnswerAnalyses).list();

        list.forEach(item -> {
            String noELeAnaleses = KnowledgeUnitService.parseCatalogName2KnowledgeFieldName(item.getAnswerAnalyses());
            item.setNoELeAnalyses(removeEle(Jsoup.parse(noELeAnaleses).body()));
        });
        Map<String, List<ExerciseEntryLib>> entryLibMap = list.stream().collect(Collectors
                .groupingBy(ExerciseEntryLib::getNoELeAnalyses));

        Map<String, List<ExamKnowledge>> knowledgeMap = new HashMap<>();

        List<ExamKnowledge> knowledgeList = examKnowledgeService.lambdaQuery().eq(ExamKnowledge::getExamBookId, "1502219859513278465")
                .isNotNull(ExamKnowledge::getOutlineDetailId).list();
        // 取得所有的P标签的内容,与答案解析去关联
        knowledgeList.forEach(item -> {
            String knowledgeText = item.getKnowledgeText();
            Elements pEles = Jsoup.parse(knowledgeText).body().getElementsByTag("p");
            for (Element pEle : pEles) {
                String key = KnowledgeUnitService.parseCatalogName2KnowledgeFieldName(pEle.html());
                List<ExamKnowledge> examKnowledges = knowledgeMap.getOrDefault(key, new ArrayList<>());
                examKnowledges.add(item);
                knowledgeMap.put(key, examKnowledges);
            }
        });

        Set<ExerciseEntryLib> entryLibList = new HashSet<>();

        matchByRateAndKnowledge(knowledgeMap, entryLibMap, entryLibList, 1f);
        matchByRateAndKnowledge(knowledgeMap, entryLibMap, entryLibList, 0.9f);
        matchByRateAndKnowledge(knowledgeMap, entryLibMap, entryLibList, 0.8f);
        matchByRateAndKnowledge(knowledgeMap, entryLibMap, entryLibList, 0.7f);
        matchByRateAndKnowledge(knowledgeMap, entryLibMap, entryLibList, 0.6f);
        matchByRateAndKnowledge(knowledgeMap, entryLibMap, entryLibList, 0.5f);
        matchByRateAndKnowledge(knowledgeMap, entryLibMap, entryLibList, 0.4f);
        matchByRateAndKnowledge(knowledgeMap, entryLibMap, entryLibList, 0.3f);

        Map<String, ExerciseGroupLib> groupLibMap = exerciseGroupLibService.lambdaQuery().list().stream()
                .collect(Collectors.toMap(ExerciseGroupLib::getId, Function.identity()));
        Map<String, ExerciseGroupLib> updateMap = new HashMap<>();
        entryLibList.forEach(exerciseEntryItem -> {
            for (java.lang.Object examDetailId : exerciseEntryItem.getExamDetailIdArray()) {
                ExerciseGroupLib exerciseGroupLib = groupLibMap.get(exerciseEntryItem.getGroupId());
                if (!exerciseGroupLib.getExamDetailIdArray().contains(examDetailId.toString())) {
                    exerciseGroupLib.getExamDetailIdArray().add(examDetailId.toString());
                    updateMap.put(exerciseEntryItem.getGroupId(), exerciseGroupLib);
                }
            }
        });
        exerciseGroupLibService.updateBatchById(updateMap.values());
    }

    private String removeEle(Element body) {
        System.out.println(body.html());
        body.getAllElements().forEach(ele -> {
            if (ele.tagName().equals("body")) {
                return;
            }
            ele.unwrap();
        });
        return StringUtils.deleteWhitespace(body.html());
    }

    /**
     * 一道题可能对应多个考点
     *
     * @param detailMap
     * @param exerciseMap
     * @param examKnowledgeList
     * @param matchRate
     */
    private void matchByRate(Map<String, ExamOutlineDetail> detailMap, Map<String, List<ExerciseEntryLib>> exerciseMap,
                             Set<ExerciseEntryLib> examKnowledgeList, float matchRate) {
        List<String> removeKeyList = Lists.newArrayList();
        for (Map.Entry<String, List<ExerciseEntryLib>> exerciseEntry : exerciseMap.entrySet()) {
            for (Map.Entry<String, ExamOutlineDetail> detailEntry : detailMap.entrySet()) {
                float jaccard = StringUtil.jaccard(detailEntry.getKey(), exerciseEntry.getKey());
                if (jaccard >= matchRate) {
                    exerciseEntry.getValue().forEach(item -> {
                        if (Objects.isNull(item.getExamDetailIdArray())) {
                            item.setExamDetailIdArray(new JSONArray());
                        }
                        if (!item.getExamDetailIdArray().contains(detailEntry.getValue().getId())) {
                            JSONArray examDetailIdArray = item.getExamDetailIdArray();
                            examDetailIdArray.add(detailEntry.getValue().getId());
                            item.setExamDetailIdArray(examDetailIdArray);
                        }
                    });
                    examKnowledgeList.addAll(exerciseEntry.getValue());
                    removeKeyList.add(exerciseEntry.getKey());
                    break;
                }
            }
        }
        // 已经匹配上的remove掉,防止数据重复
        removeKeyList.forEach(item -> {
            exerciseMap.remove(item);
        });
    }

    /**
     * 一道题可能对应多个考点
     *
     * @param knowledgeMap
     * @param exerciseMap
     * @param examKnowledgeList
     * @param matchRate
     */
    private void matchByRateAndKnowledge(Map<String, List<ExamKnowledge>> knowledgeMap, Map<String, List<ExerciseEntryLib>> exerciseMap,
                                         Set<ExerciseEntryLib> examKnowledgeList, float matchRate) {
        List<String> removeKeyList = Lists.newArrayList();
        for (Map.Entry<String, List<ExerciseEntryLib>> exerciseEntry : exerciseMap.entrySet()) {
            for (Map.Entry<String, List<ExamKnowledge>> knowledgeEntry : knowledgeMap.entrySet()) {
                float jaccard = StringUtil.jaccard(knowledgeEntry.getKey(), exerciseEntry.getKey());
                if (jaccard >= matchRate) {
                    exerciseEntry.getValue().forEach(item -> {
                        knowledgeEntry.getValue().forEach(knowledgeItem -> {
                            if (Objects.isNull(item.getExamDetailIdArray())) {
                                item.setExamDetailIdArray(new JSONArray());
                            }
                            if (!item.getExamDetailIdArray().contains(knowledgeItem.getOutlineDetailId())) {
                                JSONArray examDetailIdArray = item.getExamDetailIdArray();
                                examDetailIdArray.add(knowledgeItem.getOutlineDetailId());
                                item.setExamDetailIdArray(examDetailIdArray);
                            }
                        });
                    });
                    examKnowledgeList.addAll(exerciseEntry.getValue());
                    removeKeyList.add(exerciseEntry.getKey());
                    break;
                }
            }
        }
        // 已经匹配上的remove掉,防止数据重复
        removeKeyList.forEach(item -> {
            exerciseMap.remove(item);
        });
    }

    public void setExerciseNum() {
        List<ExamOutlineDetail> list = examOutlineDetailService.lambdaQuery().eq(ExamOutlineDetail::getExamOutlineId, "1508996261484871682").list();
        ExamOutline examOutline = examOutlineService.getById("1508996261484871682");
        List<ExerciseGroupLib> groupLibList = exerciseGroupLibService.lambdaQuery().like(ExerciseGroupLib::getExamDetailIdArray, "[\"").list();
        list.forEach(item -> {
            item.setExerciseNum(groupLibList.stream().filter(groupItem -> groupItem.getExamDetailIdArray().contains(item.getId())).count());
        });
        // 设置关联总题数
        examOutline.setExerciseNum(Long.valueOf(groupLibList.size()));
        examOutlineService.saveOrUpdate(examOutline);
        examOutlineDetailService.updateBatchById(list);
    }

    /**
     * 批量驳回医学计算器
     */
    public void rejectMedical() {
        List<TaskItem> taskItems = taskItemService.getBaseMapper()
                .executeMultiSelect("select * from task_item where knowledge_id in (select medical_calc_id from medical_calculator_field where name = '参考文献' and property like '%孟新科%' and property like '%急危重症评分%') and `status` = 2");
        taskItems.forEach(item -> {
            taskService.cancelAudit(item.getId(), item.getKnowledgeId(), "公式内图表需复核");
        });
    }

    public void initBookSummary() {
        List<Book> bookList = bookService.lambdaQuery().list();
        Map<String, BookCategory> bookCategoryMap = bookCategoryService.lambdaQuery().list().stream().collect(Collectors.toMap(BookCategory::getBiaozhunshuhao, Function.identity()));
        bookList.forEach(item -> {
            JSONObject metadata = item.getMetadata();
            metadata.put("summary", StringUtils.defaultIfBlank(bookCategoryMap.getOrDefault(item.getIsbn(), new BookCategory()).getNeirongtiyao(), ""));
            metadata.put("increase", new JSONObject());
        });
        bookService.updateBatchById(bookList);
    }

    public void batchPass() {
        List<TaskItem> itemList = taskItemService.lambdaQuery().eq(TaskItem::getTaskId, "1507257398942531586").eq(TaskItem::getStatus, 4)
                .list();
        itemList.forEach(taskItem -> {
            // 记录操作历史;
            HistoryUtils.save(taskItem.getKnowledgeId(), taskItem.getName(), History.OPERATE_PASS, History.OPERATE_RESULT_SUCCESS);
            // 修改任务项;
            taskItem.setStatus(2);
            taskItem.setName(taskItem.getName());
            taskItem.setUpdatedBy("yn");
            taskItemService.updateById(taskItem);
        });
    }


    /**
     * 导出已发布知识
     */
    public void importReleaseKnowledgeExcel() {
        // 单选或者多选
        Map<String, Map<String, String>> map = Maps.newConcurrentMap();
        List<RuleItem> ruleItemList = ruleItemService.list();
        Map<String, List<RuleItem>> ruleMap = ruleItemList.stream().collect(Collectors.groupingBy(RuleItem::getRuleId));
        Map<String, String> itemMap = null;
        for (Map.Entry<String, List<RuleItem>> m : ruleMap.entrySet()) {
            itemMap = Maps.newConcurrentMap();
            for (RuleItem ruleItem : m.getValue()) {
                itemMap.put(ruleItem.getId(), ruleItem.getName());
            }
            map.put(m.getKey(), itemMap);
        }
        List<ReleasedKnowledgeField> list = releasedKnowledgeFieldService.lambdaQuery()
                .exists("select 1 from released_knowledge where released_knowledge.knowledge_lib_id = '0001AA100000000X0120' and " +
                        " released_knowledge.id = released_knowledge_field.knowledge_id")
                .isNotNull(ReleasedKnowledgeField::getKnowledgeLibFieldId).ne(ReleasedKnowledgeField::getKnowledgeLibFieldId, "")
                .orderByAsc(ReleasedKnowledgeField::getIndex).list();
        KnowledgeAuditPack knowledgeAuditPack = new KnowledgeAuditPack();

        Set<String> tagSet = list.stream().map(ReleasedKnowledgeField::getKindValue).filter(t -> org.apache.commons.lang3.StringUtils.isNotBlank(t)).collect(Collectors.toSet());
        if (tagSet.size() > 0) {
            Map<String, String> tagMap = Maps.newConcurrentMap();
            List<Tag> allTag = tagService.queryTagByRootIdSet(tagSet);
            for (Tag tag : allTag) {
                tagMap.put(tag.getId(), tag.getName());
            }
            knowledgeAuditPack.setTagMap(tagMap);
        }
        // 应用平台
        Map<String, String> platformMap = Maps.newConcurrentMap();
        List<Platform> platformList = platformService.list();
        for (Platform platform : platformList) {
            platformMap.put(platform.getId(), platform.getName());
        }
        knowledgeAuditPack.setPlatformMap(platformMap);
        createReleaseExcel(list, knowledgeAuditPack, map);
    }

    private void createReleaseExcel(List<ReleasedKnowledgeField> list, KnowledgeAuditPack knowledgeAuditPack, Map<String, Map<String, String>> dropDownMap) {
        Map<String, Book> bookMap = bookService.lambdaQuery().in(Book::getStatus, Book.BOOK_STATUS_UNPUBLISHED, Book.BOOK_STATUS_PUBLISHED)
                .isNotNull(Book::getIsbn).ne(Book::getIsbn, "").list().stream().collect(Collectors.toMap(Book::getIsbn, Function.identity()));
        ExcelDb excelDb = new ExcelDb();
        excelDb.setSheetName("test1");
        excelDb.setTitle("test1");
        List<String> headers = list.stream().map(ReleasedKnowledgeField::getName).collect(Collectors.toList()).stream().distinct().collect(Collectors.toList());
        headers.add("id");
        headers.add("作者");
        headers.add("来源");
        headers.add("文件路径");
        excelDb.setHeaders(headers.stream().toArray(String[]::new));
        Map<String, List<ReleasedKnowledgeField>> map = list.stream().collect(Collectors.groupingBy(ReleasedKnowledgeField::getKnowledgeId));
        List<ExcelDb> excelDblist = Lists.newArrayList();
        List<String[]> data = Lists.newArrayList();
        for (List<ReleasedKnowledgeField> fieldList : map.values()) {
            String[] fieldStr = new String[headers.size()];
            for (int i = 0; i < fieldStr.length - 4; i++) {
                if (fieldList.get(i).getKind() == 1 && fieldList.get(i).getSource().size() > 0) {
                    // 处理作者
                    String isbn = fieldList.get(i).getSource().getJSONObject(0).getString("isbn");
                    Book book = bookMap.get(isbn);
                    if (Objects.nonNull(book)) {
                        fieldStr[fieldStr.length - 3] = book.getMetadata().getJSONObject("Creators")
                                .getJSONArray("Creator").stream().map(item -> ((JSONObject) item).getString("Name"))
                                .collect(Collectors.joining("、"));
                    }
                    // 处理来源
                    fieldStr[fieldStr.length - 2] = fieldList.get(i).getSource().getJSONObject(0).getString("name") + "-" +
                            fieldList.get(i).getSource().getJSONObject(0).getString("version") + "-" +
                            fieldList.get(i).getSource().getJSONObject(0).getString("isbn");
                    // 处理图片
                    fieldStr[fieldStr.length - 1] = Jsoup.parse(fieldList.get(i).getProperty()).body().getElementsByTag("img").stream()
                            .map(ele -> ele.html()).collect(Collectors.joining(";"));
                }
                fieldStr[i] = getFieldValue(fieldList.get(i), knowledgeAuditPack, dropDownMap);
            }
            fieldStr[fieldStr.length - 4] = fieldList.get(0).getKnowledgeId();
            data.add(fieldStr);
        }
        excelDb.setData(data);
        excelDblist.add(excelDb);
        excelDownload(excelDblist);
    }

    /**
     * 导出已发布知识
     */
    public void importKnowledgeImageExcel() {
        // 单选或者多选
        Map<String, Map<String, String>> map = Maps.newConcurrentMap();
        List<RuleItem> ruleItemList = ruleItemService.list();
        Map<String, List<RuleItem>> ruleMap = ruleItemList.stream().collect(Collectors.groupingBy(RuleItem::getRuleId));
        Map<String, String> itemMap = null;
        for (Map.Entry<String, List<RuleItem>> m : ruleMap.entrySet()) {
            itemMap = Maps.newConcurrentMap();
            for (RuleItem ruleItem : m.getValue()) {
                itemMap.put(ruleItem.getId(), ruleItem.getName());
            }
            map.put(m.getKey(), itemMap);
        }
        List<ReleasedKnowledgeField> list = releasedKnowledgeFieldService.lambdaQuery()
                .exists("select 1 from released_knowledge where released_knowledge.knowledge_lib_id = '0001AA100000000X0120' and " +
                        " released_knowledge.id = released_knowledge_field.knowledge_id")
                .isNotNull(ReleasedKnowledgeField::getKnowledgeLibFieldId).ne(ReleasedKnowledgeField::getKnowledgeLibFieldId, "")
                .orderByAsc(ReleasedKnowledgeField::getIndex).list();
        KnowledgeAuditPack knowledgeAuditPack = new KnowledgeAuditPack();

        Set<String> tagSet = list.stream().map(ReleasedKnowledgeField::getKindValue).filter(t -> org.apache.commons.lang3.StringUtils.isNotBlank(t)).collect(Collectors.toSet());
        if (tagSet.size() > 0) {
            Map<String, String> tagMap = Maps.newConcurrentMap();
            List<Tag> allTag = tagService.queryTagByRootIdSet(tagSet);
            for (Tag tag : allTag) {
                tagMap.put(tag.getId(), tag.getName());
            }
            knowledgeAuditPack.setTagMap(tagMap);
        }
        // 应用平台
        Map<String, String> platformMap = Maps.newConcurrentMap();
        List<Platform> platformList = platformService.list();
        for (Platform platform : platformList) {
            platformMap.put(platform.getId(), platform.getName());
        }
        knowledgeAuditPack.setPlatformMap(platformMap);
        createImageExcel(list, knowledgeAuditPack, map);
    }

    private void createImageExcel(List<ReleasedKnowledgeField> list, KnowledgeAuditPack knowledgeAuditPack, Map<String, Map<String, String>> dropDownMap) {
        Map<String, Book> bookMap = bookService.lambdaQuery().in(Book::getStatus, Book.BOOK_STATUS_UNPUBLISHED, Book.BOOK_STATUS_PUBLISHED)
                .isNotNull(Book::getIsbn).ne(Book::getIsbn, "").list().stream().collect(Collectors.toMap(Book::getIsbn, Function.identity()));
        ExcelDb excelDb = new ExcelDb();
        excelDb.setSheetName("图片");
        excelDb.setTitle("图片");
        List<String> headers = Lists.newArrayList("ID", "编号", "知识名称", "图片标题", "所属知识体系", "标签",
                "作者", "来源", "文件路径");
        excelDb.setHeaders(headers.stream().toArray(String[]::new));
        Map<String, List<ReleasedKnowledgeField>> map = list.stream().collect(Collectors.groupingBy(ReleasedKnowledgeField::getKnowledgeId));
        List<ExcelDb> excelDblist = Lists.newArrayList();
        List<String[]> data = Lists.newArrayList();
        for (List<ReleasedKnowledgeField> fieldList : map.values()) {
            ReleasedKnowledgeField richEditorField = fieldList.stream().filter(item -> item.getKind() == 1).findFirst().get();
            Elements imgEles = Jsoup.parse(richEditorField.getProperty()).body().getElementsByTag("img");
            // 处理图片
            if (imgEles.size() == 0) {
                continue;
            }
            for (int j = 0; j < imgEles.size(); j++) {
                String[] fieldStr = new String[headers.size()];
                // ID
                fieldStr[0] = fieldList.get(0).getKnowledgeId();
                // 编号
                fieldStr[1] = imgEles.get(j).attr("id");
                // 知识名称
                fieldStr[2] = getFieldValue(fieldList.stream().filter(item -> item.getName().equals("名称")).findFirst().get(), knowledgeAuditPack, dropDownMap);
                // 标题
                fieldStr[3] = parseImgInfo(imgEles.get(j));
                // 所属知识体系
                fieldStr[4] = getFieldValue(fieldList.stream().filter(item -> item.getName().equals("分类")).findFirst().get(), knowledgeAuditPack, dropDownMap);
                // 标签
                fieldStr[5] = getFieldValue(fieldList.stream().filter(item -> item.getName().equals("标签")).findFirst().get(), knowledgeAuditPack, dropDownMap);
                if (richEditorField.getSource().size() > 0) {
                    // 处理作者
                    String isbn = richEditorField.getSource().getJSONObject(0).getString("isbn");
                    Book book = bookMap.get(isbn);
                    if (Objects.nonNull(book)) {
                        fieldStr[6] = book.getMetadata().getJSONObject("Creators")
                                .getJSONArray("Creator").stream().map(item -> ((JSONObject) item).getString("Name"))
                                .collect(Collectors.joining("、"));
                    }
                    // 处理来源
                    fieldStr[7] = richEditorField.getSource().getJSONObject(0).getString("name") + "-" +
                            richEditorField.getSource().getJSONObject(0).getString("version") + "-" +
                            richEditorField.getSource().getJSONObject(0).getString("isbn");
                }
                fieldStr[8] = imgEles.get(j).attr("src");
                data.add(fieldStr);
            }
        }
        excelDb.setData(data);
        excelDblist.add(excelDb);
        excelDownload(excelDblist);
    }

    /**
     * 取得图片的图题图注
     *
     * @param img
     */
    private String parseImgInfo(Element img) {
        // 判断有没有被P包裹
        Element parentNode = img.parent();
        Element body = Jsoup.parse(parentNode.html()).body();
        body.getElementsByTag("img").remove();
        if (StringUtils.isNotBlank(body.html())) {
            parentNode = img;
        }
        // 取得上一个兄弟节点
        Element preSibling = parentNode.previousElementSibling();
        // 表题, 可能没有表题
        if (Objects.nonNull(preSibling) && StringUtils.equals(preSibling.className(), "t_title")) {
            return preSibling.html();
        }
        // 取得下一个兄弟节点
        Element nextSibling = parentNode.nextElementSibling();
        if (Objects.isNull(nextSibling)) {
            return "";
        }
        // 图题
        if (StringUtils.equals(nextSibling.className(), "p_title")) {
            return nextSibling.html();
        }
        return "";
    }
}
